#!/bin/bash
CUR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
TOP_DIR="$( cd $CUR_DIR/../ &> /dev/null && pwd )"
SUPER_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../../.." &> /dev/null && pwd )"

INSTALL_verbose=${INSTALL_verbose:-"false"}

bash_xc() {
    $INSTALL_verbose && debug="" || debug=">> /var/log/vke.log"
    bash -xc "$@ $debug"
}

set_etchosts() {
  local ip=$1
  local host=$2
  sed -i "/$host/d" /etc/hosts
  echo "$ip $host" >> /etc/hosts
}

yq_add_array() {
  local file=$1
  local yqPath=$2
  local data=$3
  local new=$(echo "[\"$data\"]" | sed 's/,/\",\"/g')
  yq -i "$yqPath += $new | $yqPath |= unique"  -o json $file
}

config_etcd() {
  useradd -r -s /sbin/nologin etcd
  mkdir -p /var/lib/etcd
  chown -R etcd:etcd /var/lib/etcd
}

config_containerd() {
    K8S_sandbox=$(kubeadm config images list --kubernetes-version=${K8S_version} | grep pause \
      | sed "s|.*/|${K8S_kubeRegistry}/|g")
    sed -i "s|sandbox_image = .*|sandbox_image = \"${K8S_sandbox}\"|g" /etc/containerd/config.toml
    if [ "${K8S_cgroupDriver}" == "systemd" ]; then
        sed -i 's/SystemdCgroup =.*/SystemdCgroup = true/g' /etc/containerd/config.toml
    fi
}

config_docker() {
  yq_add_array /etc/docker/daemon.json .insecure-registries ${K8S_kubeRegistry%/*}
  yq_add_array /etc/docker/daemon.json .exec-opts native.cgroupdriver=${K8S_cgroupDriver}
}

delete_old_versions_and_data() {
    kubeadm reset -f > /dev/null 2>&1
    rm -rf /var/lib/etcd
    rm -rf /var/lib/kubelet
    rm -rf /var/lib/kube-proxy
    rm -rf /etc/kubernetes
    rm -rf /etc/cni/net.d
    rm -rf $HOME/.kube
}

set_env() {
  mkdir -p $HOME/.kube
  sudo cp -rf /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config
  export KUBECONFIG=/etc/kubernetes/admin.conf
  sed -i '/KUBECONFIG/d' ~/.bashrc
  echo "KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bashrc
  
}


update_join_cmd() {
    local create_file=true
    local token=""
    local expire=""
    local certKey=""
    local new_file=false

    if [ -f /var/lib/vke/server/join-key ]; then
        token=$(cat /var/lib/vke/server/join-key | grep "token:" | awk '{print $2}')
        hash=$(cat /var/lib/vke/server/join-key | grep "hash:" | awk '{print $2}')
        certKey=$(cat /var/lib/vke/server/join-key | grep "certKey:" | awk '{print $2}')
        expire=$(cat /var/lib/vke/server/join-key | grep "expire:" | awk '{print $2}')
        if [ -n $token ]; then
            now=$(date +%s)
            let now=now+60
            if [ $now -lt $(date --date=$expire +%s) ]; then
                echo "has not expired, use exist token"
                create_file=false
            fi
        fi
    fi

    loop=0
    if [ $create_file == "true" ]; then
        new_file=true
        echo "create new token"
        while true; do
            token=$(kubeadm token create)
            expire=$(kubeadm token list | grep $token | awk '{print $3}')
            if [ -z "$token" ] || [ -z "$expire" ]; then
                let loop=loop+1
                if [ $loop -eq 100 ]; then
                   echo "create token timeout!!!"
                   exit
                fi
                sleep 3
            else
                break
            fi
        done
    fi


    if [ -z "$hash" ]; then
        new_file=true
        hash=$(openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt \
          | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //')
    fi

    loop=0
    if [ -z "$certKey" ]; then
        new_file=true
        echo "create new certKey"
        while true; do
            string=$(kubeadm init phase upload-certs --upload-certs)
            certKey=$(echo "$string" | tail -1)
            let loop=loop+1
            if [ -z "$certKey" ]; then
                let loop=loop+1
                if [ $loop -eq 100 ]; then
                   echo "create token timeout!!!"
                   exit
                fi
                sleep 3
            else
                break
            fi
        done
    fi

    if [ $new_file == "true" ]; then
        mkdir -p /var/lib/vke/server
        cat > /var/lib/vke/server/join-key << EOF
token: $token
hash: $hash
certKey: $certKey
expire: $expire
EOF
    fi
	kubectl delete configmap join-key --force > /dev/null 2>&1
    kubectl create configmap join-key --from-literal=token=$token --from-literal=hash=$hash --from-literal=certKey=$certKey

    echo "new token file:"
    echo "----------------------------------------------------"
    cat /var/lib/vke/server/join-key
    echo "----------------------------------------------------"
    echo "join new worker: "
    echo "    echo ${NODE_apiServerIp} ${K8S_apiServerName} >> /etc/hosts "
    echo "    kubeadm join api.k8s.local:6443 --token $token \ "
    echo "      --discovery-token-ca-cert-hash sha256:$hash"
    echo "join new controlPlane: "
    echo "    echo ${NODE_apiServerIp} ${K8S_apiServerName} >> /etc/hosts "
    echo "    kubeadm join api.k8s.local:6443 --token $token \ "
    echo "      --discovery-token-ca-cert-hash sha256:$hash \ "
    echo "      --control-plane --certificate-key $certKey \ "
    echo "      --apiserver-advertise-address  <node_internalIP>"
    echo "upgrade to controlPlane: "
    echo "    echo ${NODE_apiServerIp} ${K8S_apiServerName} >> /etc/hosts "
    echo "    kubeadm join api.k8s.local:6443 --token $token \ "
    echo "      --discovery-token-ca-cert-hash sha256:$hash \ "
    echo "      --control-plane --certificate-key $certKey"
}

create_join_cmd() {
    rm -f /var/lib/vke/server/join-key
	mkdir -p /var/lib/vke/server
	update_join_cmd
}

join_cluster() {
  if $K8S_anonymousAuth; then
    key=$(curl -k https://${K8S_apiServerName}:6443/api/v1/namespaces/default/configmaps/join-key | yq .data)
    JOIN_TOKEN=$(echo $key| yq .token)
    JOIN_HASH=$(echo $key | yq .hash)
    JOIN_CERT=$(echo $key | yq .certKey)
    echo token=$JOIN_TOKEN hash=$JOIN_HASH certKey=$JOIN_CERT
  fi

  echo "${NODE_mode} ${NODE_clusterRole} token=$JOIN_TOKEN hash=$JOIN_HASH cert=$JOIN_CERT"

  if [ -z "$JOIN_TOKEN" ] || [ -z "$JOIN_HASH" ] || [ -z "$JOIN_CERT" ]; then
    echo "cannot get join key, Join the cluster by other means: "
    echo "   JOIN_TOKEN=x JOIN_HASH=y JOIN_CERT=z $0"
    exit
  fi

  delete_old_versions_and_data
  set -x
  if [ "${NODE_clusterRole}" == "worker" ]; then
    kubeadm join ${K8S_apiServerName}:6443 --token $JOIN_TOKEN \
            --discovery-token-ca-cert-hash sha256:$JOIN_HASH
  elif [ "${NODE_clusterRole}" == "controlPlane" ]; then
    config_etcd
    if [ "${NODE_mode}" == "join" ]; then
      kubeadm join ${K8S_apiServerName}:6443 --token $JOIN_TOKEN \
        --discovery-token-ca-cert-hash sha256:$JOIN_HASH \
        --control-plane --certificate-key $JOIN_CERT \
        --apiserver-advertise-address  ${NODE_internalIP%/*}
    elif [ "${NODE_mode}" == "upgrade" ]; then
      kubeadm join ${K8S_apiServerName}:6443 --token $JOIN_TOKEN \
        --discovery-token-ca-cert-hash sha256:$JOIN_HASH \
        --control-plane --certificate-key $JOIN_CERT \
        --apiserver-advertise-address  ${NODE_internalIP%/*} \
        --skip-phases preflight  --skip-phases kubelet-start
    fi

    #systemctl daemon-reload
    #systemctl restart docker-registry

    set_env
    kubectl taint node $(hostname) node-role.kubernetes.io/master-

    #bash -c "VIP_IP=${NODE_vip} VIP_NIC=${NODE_vipInterface} ${TOP_DIR}/components/kube-vip/install.sh"
  fi
}

install_charts() {
    var_charts_dir=${K8S_vkeVarPath:-/var/lib/vke}/charts
    charts=$(yq '.CHARTS|keys|.[]' $K8S_vkeConfigPath/package-${K8S_version}.yaml)
    echo "install charts:[ $(echo $charts) ]"
    for chart in ${charts[@]}; do 
	    local chart_name=$(yq .CHARTS.$chart.name $K8S_vkeConfigPath/package-${K8S_version}.yaml)
		local version=$(yq .CHARTS.$chart.appVersion $K8S_vkeConfigPath/package-${K8S_version}.yaml)
        if [ -f $var_charts_dir/${chart_name}/${chart_name}-install.sh ]; then
            bash_xc "$var_charts_dir/${chart_name}/${chart_name}-install.sh --version=$version"
        fi
    done
}

install_kubevip() {
    install_sh=$TOP_DIR/components/kube-vip/kube-vip-install.sh
    if [ ! -f $install_sh ] && [ -f $SUPER_DIR/.pkgsInstall ]; then
        install_sh=$(cat $SUPER_DIR/.pkgsInstall | grep -E "/kube-vip-install.sh")
    else
	    var_dir=${K8S_vkeVarPath:-/var/lib/vke}
	    install_sh=$var_dir/kube-vip/kube-vip-install.sh
	fi
    if [ -n "$install_sh" ]; then
        bash_xc "$install_sh --vip=$NODE_vip --vipInterface=$NODE_vipInterface "
    fi
}

create_new_cluster() {
    NODE_clusterRole="controlPlane"

    eval "cat <<EOF
$(< ${K8S_vkeConfigPath}/init-k8s.yaml.tmpl)
EOF"  > ${K8S_vkeConfigPath}/init-k8s.yaml


    #kubeadm init
    delete_old_versions_and_data
    mkdir -p /etc/kubernetes/
	install_kubevip
	set -x
    cp -rf $K8S_vkeConfigPath/audit-policy.yaml /etc/kubernetes/
    config_etcd
    kubeadm init --config=${K8S_vkeConfigPath}/init-k8s.yaml --upload-certs >> /var/log/vke.log
    set +x

    set_env
    kubectl taint node $(hostname) node-role.kubernetes.io/master-

    # 创建新的join key
    create_join_cmd

    #6 install charts
	install_charts
    if [ "$K8S_anonymousAuth" == "true" ]; then
        kubectl apply -f $K8S_vkeConfigPath/roles.yaml
    fi
    
}

ymlToVar() {
  export $(yq e -o props $1 | grep -vE "^[[:space:]]*#|^[[:space:]]*$" | awk -F ' = ' '{gsub(/\./, "_", $1); print $1"="$2}')
}

#=========================================================
K8S_vkeConfigPath=${K8S_vkeConfigPath:-'/etc/vke'}
ymlToVar ${K8S_vkeConfigPath}/k8s.conf
ymlToVar ${K8S_vkeConfigPath}/node.yaml

if [ -n "${NODE_hostname}" ]; then
    hostnamectl set-hostname ${NODE_hostname}
    set_etchosts ${NODE_internalIP%/*} ${NODE_hostname}
fi
if [ -n "$K8S_apiServerName" ] && [ -n "$NODE_apiServerIp" ] ; then
    set_etchosts ${NODE_apiServerIp} ${K8S_apiServerName}
fi

config_containerd
config_docker

systemctl daemon-reload
systemctl restart containerd
systemctl restart docker
systemctl restart kubelet

if [ "$NODE_mode" == "create" ]; then
    create_new_cluster
else
    join_cluster
fi


